﻿using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using Atmk.WaterMeter.MIS.GateWay.CT_NBIoT.ViewModel;
using NLog;

namespace Atmk.WaterMeter.MIS.GateWay.CT_NBIoT.Utils
{
    public class HttpsUtil
    {
        private readonly Logger _logger = LogManager.GetCurrentClassLogger();

        /// <summary>
        /// 客户端证书
        /// </summary>
        public static string Selfcertpath = "Cert//outgoing.CertwithKey.pkcs12";

        /// <summary>
        /// 客户端证书密码
        /// </summary>
        public static string Selfcertpwd = "IoM@1234";

        /// <summary>
        /// 平台CA证书
        /// </summary>
        public static string Trustcapath = "Cert//client.crt";


        private readonly string _MPltip;
        private readonly int _MPltPort;

        public HttpsUtil(string platformIp, int port)
        {
            this._MPltip = platformIp;
            this._MPltPort = port;
        }

        public ApiResult PostUrl(string apiPath, string postData, WebHeaderCollection headers, string method,
            string contenttype)
        {
            return PostUrl(apiPath, postData, headers, method, contenttype, "", "");
        }

        private ApiResult PostUrl(string apiPath, string postData, WebHeaderCollection headers, string method,
            string contenttype, string p12certfile, string cerpassword)
        {
            var url = $"https://{this._MPltip}:{this._MPltPort}{apiPath}";
            ServicePointManager.ServerCertificateValidationCallback =
                new RemoteCertificateValidationCallback(ValidateServerCertificate);
            ServicePointManager.SecurityProtocol = (SecurityProtocolType) 3072;
            var httpRequest = (HttpWebRequest) WebRequest.Create(url);
            if (p12certfile.Trim().Length > 0)
                Selfcertpath = p12certfile;
            if (cerpassword.Trim().Length > 0)
                Selfcertpwd = cerpassword;
            //取销https证书
            var cerCaiShang = new X509Certificate2(Selfcertpath, Selfcertpwd);
            httpRequest.ClientCertificates.Add(cerCaiShang);
            httpRequest.Method = method;
            httpRequest.ContentType = contenttype;
            httpRequest.Referer = null;
            httpRequest.AllowAutoRedirect = true;
            httpRequest.UserAgent =
                "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
            httpRequest.Accept = "*/*";
            for (var i = 0; i < headers.Count; i++)
            {
                for (var j = 0; j < headers.GetValues(i).Length; j++)
                {
                    httpRequest.Headers.Add(headers.Keys[i], headers.GetValues(i)[j]);
                }
            }
            if (method != "GET")
            {
                var requestStem = httpRequest.GetRequestStream();
                var sw = new StreamWriter(requestStem);
                sw.Write(postData);
                sw.Close();
            }
            HttpWebResponse httpResponse;
            var error = false;

            //try
            //{
            //    _logger.Debug("进入PostUrl_13_0:");
            //    httpResponse = (HttpWebResponse) httpRequest.GetResponse();
            //}
            ////catch (WebException we)
            //catch (Exception ex)
            //{
            //    //httpResponse = (HttpWebResponse) we.Response;
            //    _logger.Debug("进入PostUrl_13_1:"+ ex.Message);
            //    _logger.Debug("进入PostUrl_13_2:" + ex.StackTrace);
            //    error = true;
            //}
            try
            {
                httpResponse = (HttpWebResponse)httpRequest.GetResponse();
            }
            catch (WebException we)
            {
                httpResponse = (HttpWebResponse)we.Response;
                error = true;
            }
            var receiveStream = httpResponse.GetResponseStream();
            string result;
            using (var sr = new StreamReader(receiveStream ?? throw new InvalidOperationException("PostUrl:获取流数据为空")))
            {
                result = sr.ReadToEnd();
            }
            if (error)
                throw new Exception($"{httpResponse.StatusCode.ToString()}:{result}");
            var r = new ApiResult
            {
                Result = result,
                StatusCode = (int) httpResponse.StatusCode
            };
            return r;
        }

        private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain,
            SslPolicyErrors sslpolicyerrors)
        {
            //获取本地ca
            var caCertificate2 = new X509Certificate2(Trustcapath);
            _logger.Info(certificate.Subject);
            _logger.Info(certificate.Issuer);
            _logger.Info(sslpolicyerrors.ToString());
            var result = certificate.Issuer == caCertificate2.IssuerName.Name;
            if (!result)
                result = certificate.Issuer == caCertificate2.Subject;//多级证书，有一个匹配即可原因
            return result;
        }
    }
}